/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

#ifndef __DHLPACKET
#define __DHLPACKET

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "dhl-config.h"

/* 
 * The following 2 structs are the xbee structs used for transmitting and
 * receiving data over xb. The final struct is the DHL header.
 *
 * FIXME: most of the CUPIC build_... functions ask for a packet size.
 * Since error checking isn't really possible on the CUPIC, this maximum
 * packet size is unused.
 */

struct xb_tx_hdr {
    cu_uchar_t delimeter;
    cu_uint_t size;
    cu_uchar_t identifier;
    cu_uchar_t response;
    cu_uint_t dest;
    cu_uchar_t disable_ack;
} ATTRIBUTE_PACKED;


struct xb_rx_hdr {
    cu_uchar_t delimeter;
    cu_uint_t size;
    cu_uchar_t frame_type;
    cu_uint_t dest;
    cu_uchar_t rssi_power;
    cu_uchar_t options;
} ATTRIBUTE_PACKED;


struct dhl_hdr {
    cu_uint_t src;
    cu_uint_t dst;
    cu_uint_t size;
    cu_uchar_t type;
    cu_uchar_t seq;
} ATTRIBUTE_PACKED;


#define XB_DELIMETER      (0x7E)
#define XB_RX_PAYLOAD     (sizeof(struct xb_rx_hdr))
#define XB_TX_PAYLOAD     (sizeof(struct xb_tx_hdr))
#define DHL_PAYLOAD       (XB_RX_PAYLOAD + sizeof(struct dhl_hdr))
#define CAPABILITY_SIZE   (sizeof(DHL_Capabilities_t))
#define CSUM_START        (3) // bytes 0-2 + checksum

// This switches the byte order of a uint (2 bytes)
// All XB Headers must use it
cu_uint_t cupic_to_xb(cu_uint_t var);

// Create the xbee header in the space pointed to by *hdr
void build_xbee_header(
    struct xb_tx_hdr *hdr,  // the buffer you want to fill
    cu_uint_t size,         // the size of the xbee packet
    cu_uint_t dest          // the destination of the xbee packet
);

// Given an empty buffer of sufficient size, fill it with 
void build_dhl_header(
    struct dhl_hdr *hdr,    // the buffer you want to fill
    cu_uint_t size,         // payload size
    cu_uint_t src,          // the sender of the packet
    cu_uint_t dst,          // the receiver of the packet
    cu_uchar_t type,        // the payload's capability type/id
    cu_uchar_t seq          // a sequence number
);

// 
cu_uint_t build_led_packet(
    cu_uchar_t *buf,        // the buffer you want to fill
    cu_uint_t buf_size,     // the maximimum size of the buffer (FIXME: this isn't checked and is currenlty unused)
    cu_uint_t src,          // the address of the node sending the packet
    cu_uint_t dest,         // the packet destination address
    cu_uchar_t seq_num,     // a sequence number
    cu_uchar_t cmd          // the value to set the LEDs to
);

cu_uint_t build_stream_request(
  cu_uchar_t *buf,          // the buffer you want to fill 
  cu_uint_t buf_size,       // the max buffer size (FIXME: currently is unused)
  cu_uint_t subscriber,     // the XB address of the subscriber
  cu_uint_t dest,           // the XB address of the destination
  cu_uchar_t seq_num,       // a sequence number
  cu_uchar_t cmd,           // the capability you are subscribing too
  cu_uchar_t start          // should the publisher start (true) or stop (0) publishing?
);

// Create a 1 byte checksum
unsigned char build_checksum(
    cu_uchar_t *buf,        // the buffer to checksum
    int start,              // the starting byte location
    int end                 // the ending byte location
);


#ifdef CUPIC
// Recieves a message. This function also acks the message (if it is a command)
void dhl_message_recieved();

// Determine which data needs to be published and publishes it
// It calls the appropriate build_... functions
void stream_data(void);

// create a dhl_capabilities packet
// note that the default destination addresss is the coordinator
cu_uint_t build_dhl_capabilities(
    cu_uchar_t *buf,        // the buffer you want to fill
    cu_uint_t src,          // the node sending the capabilities packet
    cu_uchar_t seq_num      // a sequnce number
);

// create a custody packet 
cu_uint_t build_dhl_custody(
    cu_uchar_t *buf,        // the buffer you want to fill
    cu_uint_t src,          // the node source
    cu_uint_t dest,         // the destination address
    cu_uchar_t seq_num      // a sequence number
);

// create what build_packet.c calls a "debug packet"
// the only difference between debug_packet() and build_debug_packet() is 
// that this function does not send the packet (and is a lot cleaner imho)
cu_uint_t build_debug_packet(
    cu_uchar_t *buf,        // the buffer you want to fill
    cu_uint_t max_size,     // the buffer's maximum size (FIXME: unused)
    cu_uint_t dest,         // the destination address
    cu_uint_t seq_num       // a sequence number
);

// create what build_packet.c calls a "data packet"
cu_uint_t build_data_packet(
    cu_uchar_t *buf,        // the buffer you want to fill
    cu_uint_t max_size,     // the buffer's maximum size
    cu_uint_t dest,         // the destination address
    cu_uint_t seq_num       // a sequence number
);


// create what build_packet.c calls a "data packet"
cu_uint_t build_house_keeping_packet(
    cu_uchar_t *buf,        // the buffer to fill
    cu_uint_t dest,         // the destination node address
    cu_uint_t max_size      // the maximum buffer size
);


// create what build_packet.c calls a "high speed packet"
cu_uint_t build_high_speed_packet(
    cu_uchar_t *buf,        // the buffer to fill
    cu_uint_t dest,         // the destination address
    cu_uint_t max_size      // the maximum buffer size (FIXME: unused)
);

#endif //CUPIC

#ifdef __cplusplus
};
#endif  /* __cplusplus */

#endif
